{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "9c10cc0b",
   "metadata": {},
   "source": [
    "## 注意易错点：\n",
    "    1.df.pivot_table 是df\n",
    "    2.最后的return 是[]不是() \n",
    "    user_ratings[similar_items] similarity_score[similar_items_index]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "c2e78c46",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn.metrics.pairwise import cosine_similarity"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "e990b3ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.read_csv('./data/book/BX-Book-Ratings.csv',sep=';',encoding='latin-1',usecols=['User-ID','ISBN','Book-Rating'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d167519",
   "metadata": {},
   "outputs": [],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6eae7fe3",
   "metadata": {},
   "source": [
    "1.构建评分矩阵rating_matrix，将缺失值填充为 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a24d179f",
   "metadata": {},
   "outputs": [],
   "source": [
    "#由考生填写\n",
    "rating_matrix = df.pivot_table(index='User-ID',columns='ISBN',values='Book-Rating')\n",
    "rating_matrix.fillna(0,inplace=True)\n",
    "rating_matrix\n",
    "#由考生填写"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39883b13",
   "metadata": {},
   "source": [
    "2.使用cosine_similarity函数计算项目相似度矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bf6be954",
   "metadata": {},
   "outputs": [],
   "source": [
    "#  计算相似度矩阵\n",
    "#由考生填写\n",
    "item_similarity_matrix = cosine_similarity(rating_matrix.T)\n",
    "item_similarity_matrix\n",
    "#由考生填写"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "ba17483a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 将rating_matrix的索引转换为字符串\n",
    "rating_matrix.index=rating_matrix.index.map(str)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8a8721de",
   "metadata": {},
   "source": [
    "3.在用户评分过的物品中获取与 item 相似的物品\n",
    "注意：for 下面的if else 是和for同层级的，如果写成上下级，结果显示为None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "65c976fc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义预测用户对书籍的评分函数\n",
    "def predict_rating(user,item):\n",
    "    # 获取item的索引\n",
    "    #由考生填写\n",
    "    item_index = rating_matrix.columns.get_loc(item)\n",
    "    #由考生填写\n",
    "    # 获取item的相似度分数\n",
    "    similarity_score = item_similarity_matrix[item_index]\n",
    "    # 获取用户评分\n",
    "    user_ratings = rating_matrix.loc[user]\n",
    "    # 获取用户评分过的物品\n",
    "    rated_items = user_ratings[user_ratings>0].index\n",
    "    # 在用户评分过的物品中获取与item相似的物品\n",
    "    #由考生填写\n",
    "    similar_items = [item for item in rated_items if item_similarity_matrix[item_index][rating_matrix.columns.get_loc(item)]>0]\n",
    "    #由考生填写\n",
    "    similar_items_index = []\n",
    "    for i in range(len(similar_items)):\n",
    "        similar_items_index.append(rating_matrix.columns.get_loc(similar_items[i]))\n",
    "    # 如果没有相似的物品，则返回 0\n",
    "    if len(similar_items) == 0:\n",
    "        #print('len_similar_items == 0')\n",
    "        return 0\n",
    "    # 否则，计算用户对item的预测评分\n",
    "    else:\n",
    "        #print('len_similar_items != 0')\n",
    "        #由考生填写\n",
    "        return user_ratings[similar_items].dot(similarity_score[similar_items_index])/similarity_score[similar_items_index].sum()\n",
    "        #由考生填写 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "c5872778",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "预测用户276729对书籍0064401367的评分为：0\n"
     ]
    }
   ],
   "source": [
    "#  测试\n",
    "user = '276729'\n",
    "item = '0064401367'\n",
    "predicted_rating1 = predict_rating(user,item)\n",
    "print('预测用户{}对书籍{}的评分为：{}'.format(user,item,predicted_rating1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "40859117",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "预测用户278259对书籍0020259700的评分为：10.0\n"
     ]
    }
   ],
   "source": [
    "# 测试，计算用户 278259 对书籍 0020259700 的预测评分\n",
    "user = '278259'\n",
    "item = '0020259700'\n",
    "predicted_rating2 = predict_rating(user,item)\n",
    "print('预测用户{}对书籍{}的评分为：{}'.format(user,item,predicted_rating2))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "PySpark-2.4.5",
   "language": "python",
   "name": "pyspark-2.4.5"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
